package org.activequant.core.domainmodel.marketscanner;

import java.io.Serializable;
import java.util.List;

import org.activequant.core.types.TimeStamp;
import org.activequant.core.util.ScanDataTimeSeriesUtils;
import org.activequant.util.exceptions.ValueNotFoundException;
import org.activequant.util.tools.ArrayUtils;

/**
* A ScanDataTimeSeries(ArrayList subclass) whose elements are MarketScan objects.
* Holds the following inherited/associated variables:
* <ul>
* <li>id(Long)</li>
* <li>marketScanSeriesSpecification(MarketScanSeriesSpecification)</li>
* <li>inherited list of elements (List&lt;MarketScan&gt;)</li>
* </ul>
*  @author Dimitar Misev
*/
public class MarketScanSeries extends ScanDataTimeSeries<MarketScan> implements Serializable {

	private static final long serialVersionUID = 7075375398315155768L;
	
	/**
	 * an empty MarketScanSeries constructor.
	 *
	 */
	public MarketScanSeries() {
		super();
	}
	
	/**
	 * Constructs a MarketScanSeries(ArrayList and ScanDataTimeSeries subclass) using the given marketScans(MarketScan...) to set its MarketScan elements.<br/>
	 * Their timeStamp(TimeStamp)'s must be ordered from newest(at index=0) to oldest(at index=n)
	 * @param marketScans
	 *
	 */
	public MarketScanSeries(MarketScan... marketScans) {
		setMarketScans(marketScans);
	}
	/**
	 * Constructs a MarketScanSeries(ArrayList and ScanDataTimeSeries subclass) using the given marketScanSeriesSpecification(MarketScanSeriesSpecification) and marketScans(MarketScan...) to set its associated 
	 * marketScanSeriesSpecification(MarketScanSeriesSpecification) and its MarketScan elements.<br/>
	 * Their timeStamp(TimeStamp)'s must be ordered from newest(at index=0) to oldest(at index=n)
	 * @param marketScanSeriesSpecification
	 * @param marketScans
	 */
	public MarketScanSeries(MarketScanSeriesSpecification marketScanSeriesSpecification, MarketScan... marketScans) {
		this(marketScans);
		setMarketScanSeriesSpecification(marketScanSeriesSpecification);
	}
	
	/**
	 * Constructs a MarketScanSeries(ArrayList and ScanDataTimeSeries subclass) using the given marketScans(List&lt;MarketScan&gt;) to set its MarketScan elements.<br/>
	 * Their timeStamp(TimeStamp)'s must be ordered from newest(at index=0) to oldest(at index=n).    
	 * @param marketScans
	 */
	public MarketScanSeries(List<MarketScan> marketScans) {
		super(marketScans);
		assert(ScanDataTimeSeriesUtils.isOrderValid(this));
	}
	/**
	 * applies a given series specification to the series itself and all elements<br/>
	 * <strong>1.</strong> sets the associated marketScanSeriesSpecification(MarketScanSeriesSpecification) with the given marketScanSeriesSpecification(MarketScanSeriesSpecification)<br/>
	 * <strong>2.</strong> sets the scanCriteria(ScanCriteria) and timeFrame(TimeFrame) of each of the MarketScan elements of this MarketScanSeries(ArrayList and ScanDataTimeSeries subclass)
	 * with the scanCriteria(ScanCriteria) and timeFrame(TimeFrame) of the given marketScanSeriesSpecification(MarketScanSeriesSpecification)
	 */
	@Override
	public void applySeriesSpecification(MarketScanSeriesSpecification marketScanSeriesSpecification) {
		assert(marketScanSeriesSpecification!=null);
		this.marketScanSeriesSpecification = marketScanSeriesSpecification;
		for(MarketScan object : this) {
			object.setScanCriteria(marketScanSeriesSpecification.getScanCriteria());
			object.setTimeFrame(marketScanSeriesSpecification.getTimeFrame());
		}
	}
	/**
	 * Sets the elements of this MarketScanSeries(ArrayList and TimeSeries subclass) with the given marketScans(MarketScan...).<br/>
	 * Their timeStamp(TimeStamp)'s must be ordered from newest(at index=0) to oldest(at index=n)
	 * @param marketScans
	 */
	public void setMarketScans(MarketScan... marketScans) {
		setMarketScans(ArrayUtils.asList(marketScans));
	}
	/**
	 * Sets the elements of this MarketScanSeries(ArrayList and ScanDataTimeSeries subclass) with the given marketScans(List&lt;MarketScan&gt;).<br/>
	 * Their timeStamp(TimeStamp)'s must be ordered from newest(at index=0) to oldest(at index=n)
	 * @param marketScans
	 */
	public void setMarketScans(List<MarketScan> marketScans) {
		assert(ScanDataTimeSeriesUtils.isOrderValid(this));
		clear();
		addAll(marketScans);
	}
	/**
	 * returns a MarketScan[] array containing the elements of this MarketScanSeries(ArrayList and ScanDataTimeSeries subclass)
	 * @return
	 */
	public MarketScan[] getMarketScans() {
		return ArrayUtils.asArray(this, MarketScan.class);
	}
	
	
	public MarketScanSeries clone() {
		MarketScan[] clonedMarketScans = new MarketScan[size()];
		MarketScan[] marketScans = toArray(new MarketScan[]{});
		for(int i = 0; i < marketScans.length; i++) {
			clonedMarketScans[i] = marketScans[i].clone();
		}
		MarketScanSeries clone = new MarketScanSeries(marketScanSeriesSpecification, clonedMarketScans);
		return clone; 
	}
	/**
	 * returns a MarketScanSeries containing the MarketScan elements whose TimeStamps are within(inclusive) the given start-end(TimeStamp) interval
	 */
	public MarketScanSeries getTimeFrame(TimeStamp start, TimeStamp end) {
		return (MarketScanSeries) super.getTimeFrame(start, end);
	}
	/**
	 * returns a MarketScanSeries containing the MarketScan elements within(inclusive) the given start-end(int) index interval
	 */
	public MarketScanSeries subList(int start, int end) throws ValueNotFoundException {
		return (MarketScanSeries) super.subList(start, end);
	}
	/**
	 * returns a MarketScanSeries containing the MarketScan elements whose TimeStamps are within(inclusive) the given start-end(TimeStamp) interval
	 */
	public MarketScanSeries subList(TimeStamp start, TimeStamp end) throws ValueNotFoundException {
		return (MarketScanSeries) super.subList(start, end);
	}
}